﻿/*
 * DATAFLOWCORE
 * 
Copyright 2012 - Mindstorm Multitouch Limited

Author - Bertrand Nouvel

DataFlowCore is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

DataFlowCore is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser Public License for more details.
*/



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MongoDB.Bson;

namespace DFlow
{
    /// <summary>
    /// Net Wires are node monitors that transmit the data in push to another DFlow node.
    /// </summary>
    public class NetWire : NodeMonitor
    {
        public DFlow.Node srcnode;
        public string dstnode;
        public DFlowCore.Network.IListener dsthost;
        public object iep;
        public string srcpin;
        public string dstpin;
        public bool reliable = false;
        public string id;

        public bool expired = false;

        protected int stat_nused = 0;
        protected float last_stat_display;
        protected float last_emit = -1;
        protected float min_delay = -1;

        //bool conversion;
        public override string ToString()
        {
            return System.String.Format("{0}@{1}-@->{2}@{3}@{4}", srcpin, srcnode.name, dstpin, dstnode, iep.ToString());
        }

        public NetWire(Node sn, string sp, DFlowCore.Network.IListener dh, string dn, string dp, bool r, float maxfreq = 25)
        {
            dsthost = dh;
            srcnode = sn; dstnode = dn; srcpin = sp; dstpin = dp;
            reliable = r;
            if (maxfreq > 0)
            {
                this.min_delay = 1f / maxfreq;
            }
            iep = dsthost.GetCurrentRemoteEndpoint();
            id = System.String.Format("netwire-({1})-{0}", DFlowCore.Time.time, ToString());
            last_stat_display = DFlowCore.Time.time;
        }

        public override void OnPostProcess()
        {

            if ((this.min_delay < 0) || (DFlowCore.Time.time - last_emit > this.min_delay))
            {
                object o = srcnode.GetType().GetField(srcpin).GetValue(srcnode);
                BsonDocument args = new BsonDocument();
                args.Add("value", DFlowCore.BsonUtils.BsonEncode(o, srcnode.GetInputType(srcpin)));
                args.Add("dstpin", dstpin);
                args.Add("dstnode", dstnode);
                args.Add("dstDataflow", null);

                BsonDocument res = new BsonDocument();
                res.Add("cmd", "set_node_value");
                res.Add("args", args);
                //res.Add("netwire", this.ToString());
                res.Add("reply", "none");

                byte[] b = DFlowCore.BsonUtils.Encode(res);


                if (dsthost.IsConnectedTo(iep))
                {
                    if (reliable)
                    {
                        dsthost.SendAsyncPacket(b, iep);
                    }
                    else
                    {
                        dsthost.SendAsyncUDPPacket(b, iep);
                    }
                }
                else
                {
                    expired = true;
                    return;
                }


                last_emit = DFlowCore.Time.time;
                if ((++stat_nused) % 100 == 0)
                {
                    float wfps = 1f / ((DFlowCore.Time.time - last_stat_display) + float.Epsilon);
                    System.Diagnostics.Debug.Print("NetWire Stats :" + id + ":" + wfps.ToString());
                    last_stat_display = DFlowCore.Time.time;
                }
            }
        }
    }

}
